package com.meta.platform.login.plus.wechat.http;

import java.lang.reflect.Field;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.meta.framework.common.exception.BaseException;
import com.meta.framework.common.utils.StringUtils;
import com.meta.platform.login.plus.common.annotations.WeChatField;
import com.meta.platform.login.plus.common.constants.WeChatConstants;
import com.meta.platform.login.plus.wechat.http.req.JsCode2SessionRequest;
import com.meta.platform.login.plus.wechat.http.req.WeChatBaseRequest;
import com.meta.platform.login.plus.wechat.http.resp.JsCode2SessionResponse;
import com.meta.platform.login.plus.wechat.http.resp.WeChatBaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.stereotype.Component;

import com.meta.framework.http.HttpUtil;

/**
 * 微信小程序客户端
 *
 * @author pengjianfeng
 * @version 1.0
 * @date 2021/1/21 6:21 下午
 */
@Slf4j
@Component
public class WeChatClient {
    
    /**
     * jsCode换取session
     * 
     * @param request
     * @return
     */
    public JsCode2SessionResponse jsCode2Session(JsCode2SessionRequest request) {
        Map<String, String> requestParam = this.getRequestParam(request);
        String result = HttpUtil.get(WeChatConstants.WECHAT_API_BASE_URL + "/sns/jscode2session", requestParam, true);
        return this.parseResponse(result, JsCode2SessionResponse.class);
    }
    
    /**
     * 获取请求参数
     * 
     * @param request
     * @return
     */
    private Map<String, String> getRequestParam(WeChatBaseRequest request) {
        Map<String, String> paramMap = new HashMap<>();
        Field[] fields = FieldUtils.getFieldsWithAnnotation(request.getClass(), WeChatField.class);
        Arrays.stream(fields).forEach(field -> {
            try {
                field.setAccessible(true);
                WeChatField annotation = field.getAnnotation(WeChatField.class);
                String fieldName = StringUtils.isNotBlank(annotation.value()) ? annotation.value() : field.getName();
                String fieldValue = field.get(request).toString();
                paramMap.put(fieldName, fieldValue);
            }
            catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });
        
        return paramMap;
    }
    
    private <T extends WeChatBaseResponse> T parseResponse(String json, Class<T> clazz) {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        
        try {
            T t = clazz.getDeclaredConstructor().newInstance();
            JSONObject jsonObject = JSON.parseObject(json);
            List<Field> fields = FieldUtils.getFieldsListWithAnnotation(clazz, WeChatField.class);
            
            for (int i = 0; i < fields.size(); i++) {
                fields.get(i).setAccessible(true);
                WeChatField annotation = fields.get(i).getAnnotation(WeChatField.class);
                String key = StringUtils.isNotBlank(annotation.value()) ? annotation.value() : fields.get(i).getName();
                FieldUtils.writeField(fields.get(i), t, jsonObject.get(key));
            }
            
            return t;
        }
        catch (Exception e) {
            log.error("WeChat message parse error", e);
            throw new BaseException("微信消息解析失败");
        }
    }
}
